module main

import veb
import db.sqlite
import log
import json
import time

fn main() {
	mut app := &App{}
	db := sqlite.connect('records.db') or { panic(err) }
	app.db = db

	sql db {
		create table Record
		create table Setting
	}!

	init_db_default_data(db)

	app.mount_static_folder_at('./view', '/')!
	println('Hello from math-server!')

	app.use(handler: print_request_info)

	veb.run[App, Context](mut app, 3001)
}

fn init_db_default_data(db sqlite.DB) {
	settings := sql db {
		select from Setting where name == 'settings'
	} or { [] }

	log.info('init default setting')

	if settings.len <= 0 {
		log.info('no setting in db now')
		default_setting := Setting{
			exercise_count: 10
			name: 'settings'
		}
		sql db {
			insert default_setting into Setting
		} or { panic(err) }
	}
}

pub struct App {
	veb.StaticHandler
	veb.Middleware[Context]
mut:
	db sqlite.DB
}

pub fn print_request_info(mut ctx Context) bool {
	log.info('[veb] before_request: ${ctx.req.method} ${ctx.req.url} data: ${ctx.req.data}')
	return true
}

type Data = Setting | []Record

struct Message {
	code    int
	message string
	data    Data
}

@['/settings'; get]
pub fn (app &App) setttings(mut ctx Context) veb.Result {
	settings := sql app.db {
		select from Setting limit 1
	} or { [] }

	dump(settings)

	if settings.len <= 0 {
		return ctx.json(Message{
			code: 1
			message: 'interal data error'
		})
	}

	setting := settings.first()
	return ctx.json(Message{ data: setting })
}

pub fn (app &App) get_records(mut ctx Context) veb.Result {
	records := sql app.db {
		select from Record order by created desc limit 15
	} or { [] }

	// data := json.encode(records)
	return ctx.json(Message{ data: records })
}

@[post]
pub fn (app &App) update_settings(mut ctx Context) veb.Result {
	log.info('try to update_settings')

	setting := json.decode(Setting, ctx.req.data) or {
		return ctx.json(Message{ code: 1, message: 'invalid data' })
	}

	// sql app.db {
	// 	update Setting set exercise_count = setting.exercise_count
	// } or {  }

	sql app.db {
		update Setting set exercise_count = setting.exercise_count where name == 'settings'
	} or {
	}
	log.info('exercise_count upated: ${setting.exercise_count}')
	return ctx.json(Message{ code: 0 })
}

@[post]
pub fn (app &App) add_record(mut ctx Context) veb.Result {
	log.info('try to add new record')

	mut record := json.decode(Record, ctx.req.data) or {
		return ctx.json(Message{ code: 1, message: 'invalid data' })
	}
	record.created = time.now().format_ss()
	record.total_seconds = record.minute * 60 + record.second

	sql app.db {
		insert record into Record
	} or {
		// return  ctx.json(Message{})
	}

	return ctx.json(Message{ code: 0 })
}

pub struct Context {
	veb.Context
}

@[table: 'records']
struct Record {
mut:
	err_count     int
	minute        int
	second        int
	created       string @[primary]
	total_seconds int
}

@[table: 'settings']
struct Setting {
	name           string @[primary]
	exercise_count int
}
